class User < ActiveRecord::Base
  has_many :laivs, :foreign_key => 'administrator_id', :dependent => :nullify
  has_many :laiv_users
  has_many :application_forms
  has_many :accepted_application_forms, :class_name => "ApplicationForm",
    :conditions => "status=#{ApplicationForm::STATUS_ACCEPTED}"
  has_many :participation_laivs, 
    :through => :accepted_application_forms, :source => :laiv

  validates_presence_of :email
  validates_uniqueness_of :email
  validates_format_of :email,
    :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
    :message => "format is incorrect"

  validates_format_of :sex, :with => /[MF]/i, :message => "must be F or M"

  validates_inclusion_of :birthdate,
    :in => Date.new(1900,1,1)..1.day.ago.to_date,
    :message => "is out of range (in the future or too old)"

  validates_length_of :password, :minimum => 5, :on => :create

  def password
    @password
  end

  def password=(pwd)
    @password = pwd
    create_new_salt
    self.hashed_password = User.encrypted_password(self.password, self.seed)
  end

  # Attempts to delete the user, but it fails when the user is an administrator
  # or is the last superadministrator.
  def safe_destroy
    if laivs.count > 0
      raise "Can't delete a laiv administrator"
    else
      if superadmin and User.count(:superadmin, true) <= 1
        raise "Can't delete the last superadmin"
      else
        destroy
      end
    end
  end

  # Attempts to find a user with e-mail +email+ and password +password+.
  # Returns the user if successful, and nil otherwise.
  def self.authenticate(email, password)
    user = self.find_by_email(email)
    if user
      expected_password = encrypted_password(password, user.seed)
      if user.hashed_password != expected_password
        user = nil
      end
    end
    user
  end
	
  private
  
  # Returns an encrypted version of string +password+ using SHA1
  # and salt +salt+.
  def self.encrypted_password(password, salt)
    string_to_hash = password + "tapeus" + salt
    Digest::SHA1.hexdigest(string_to_hash)
  end

  # Creates a new random salt and saves it in the object's state
  def create_new_salt
    self.seed = self.object_id.to_s + rand.to_s
  end
end
